//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved

#include "pch.h"
#include "SoundEffect.h"
#include "DirectX\DirectXHelper.h"

namespace
{
}

SoundEffect::SoundEffect():
	m_audioAvailable(false)
{
}

//----------------------------------------------------------------------

void SoundEffect::Initialize(
	_In_ IXAudio2 *masteringEngine,
	_In_ WAVEFORMATEX *sourceFormat,
	_In_ Platform::Array<byte>^ soundData)
{
	m_soundData = soundData;

	m_voiceCallback = std::shared_ptr<VoiceCallback>(new VoiceCallback(&m_playing));

	if (masteringEngine == nullptr)
	{
		// Audio is not available so just return.
		m_audioAvailable = false;
		return;
	}

	// Create a source voice for this sound effect.
	DX::ThrowIfFailed(
		masteringEngine->CreateSourceVoice(
			&m_sourceVoice,
			sourceFormat,
			0,
			XAUDIO2_DEFAULT_FREQ_RATIO,
			m_voiceCallback.get(),
			nullptr,
			nullptr
			)
		);
	m_audioAvailable = true;
}

//----------------------------------------------------------------------

void SoundEffect::Play(_In_ float volume, _In_ bool loop)
{
	XAUDIO2_BUFFER buffer = {0};

	if (!m_audioAvailable)
	{
		// Audio is not available so just return.
		return;
	}

	// Interrupt sound effect if it is currently playing.
	DX::ThrowIfFailed(
		m_sourceVoice->Stop()
		);
	DX::ThrowIfFailed(
		m_sourceVoice->FlushSourceBuffers()
		);

	// Queue the memory buffer for playback and start the voice.
	buffer.AudioBytes = m_soundData->Length;
	buffer.pAudioData = m_soundData->Data;
	buffer.Flags = XAUDIO2_END_OF_STREAM;

	if(loop)
		buffer.LoopCount = XAUDIO2_MAX_LOOP_COUNT;

	DX::ThrowIfFailed(
		m_sourceVoice->SetVolume(volume)
		);
	DX::ThrowIfFailed(
		m_sourceVoice->SubmitSourceBuffer(&buffer)
		);
	DX::ThrowIfFailed(
		m_sourceVoice->Start()
		);
}

void SoundEffect::SetVolume(float volume)
{
	DX::ThrowIfFailed(
		m_sourceVoice->SetVolume(volume)
		);
}

//----------------------------------------------------------------------

void SoundEffect::Stop(bool waitUntilEnd)
{
	if(waitUntilEnd)
	{
		DX::ThrowIfFailed(
			m_sourceVoice->ExitLoop()
		);
	}
	else
	{
		DX::ThrowIfFailed(
			m_sourceVoice->Stop()
		);
	}

	DX::ThrowIfFailed(
		m_sourceVoice->FlushSourceBuffers()
	);
}
